package cn.org.timespace.easyframe.util.report.model;




import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.org.timespace.easyframe.util.report.expression.Evaluator;



/**
 * ��ż�����
 * 
 * ��ͨ������㹫ʽ4�����ŵļ�����<p>
 * �羻���еı�ż��㹫ʽΪ:<p>
 * sum(����)-sum(����)<p>
 * Ŀǰ֧�ֵľۼ�������sum(�м���),avg(�м���),count()<p>
 * 
 * �����ż�����Ӧͬʱʹ��addRelativeColumnKey(�м���,�м�)���������<p>
 * Ҳ��ʹ��addRelativeColumn(Column)4����,��ʱ���м���Ϊ�еı���,�м�Ϊ�еļ�
 *
 *
 */
public class FootComputeColumn extends FootColumn{

	HashMap relativeColumnKeys = new HashMap();
	String expression = "";
    String rowKeySub = "";
	public FootComputeColumn(Foot foot, Column positionColumn) {
		super(foot, positionColumn);
	}
	public FootComputeColumn(Foot foot, Column positionColumn,LabelProvider labelProvider) {
		super(foot, positionColumn,labelProvider);
	}

	public String getExpression() {
		return expression;
	}

	public void setExpression(String expression) {
		this.expression = expression;
	}

	public void addRelativeColumn(Column column) {
		this.relativeColumnKeys.put(column.getTitle(), column.getKey());
	}

	public void addRelativeColumnKey(String name, Object columnKey) {
		this.relativeColumnKeys.put(name, columnKey);
	}
	
	

	/**
	 * �л���
	 * @param exp
	 * @return
	 */
	private double computeSum(String exp,GroupCell gc) {
		double sum=0;
		for(Iterator itr=gc.getRowKeys().iterator();itr.hasNext();){			
			sum += eval(exp, getParams(itr.next()));
		}
		return sum;
	}

	/**
	 * ��ƽ��ֵ
	 * @param exp
	 * @return
	 */
	private double computeAvg(String exp,GroupCell gc) {
		double sum=0;
		int count=0;
		for(Iterator itr=gc.getRowKeys().iterator();itr.hasNext();){
			sum += eval(exp, getParams(itr.next()));
			count++;
		}
		return count==0 ? 0 : sum/count;
	}
    /**
     * ����ָ����ʱ������
     * 
     * @param exp
     * @param gc
     * @param rowSubStr
     * @return
     */
	private double computeSumByRowKey(String exp,GroupCell gc,String rowSubStr){
		double sum=0;
		for(Iterator itr= gc.getRowKeys().iterator();itr.hasNext();){
			String rowkey = itr.next().toString();
			if(rowkey.lastIndexOf(rowSubStr)>0){
				sum+=eval(exp,getParams(rowkey));
			}
			
		}
		return sum;
	}
	/**
	 * ָ������ƽ��ֵ
	 * @param exp
	 * @param gc
	 * @param rowSubStr
	 * @return
	 */
	private double computeAvgByRowKey(String exp,GroupCell gc,String rowSubStr){
		double sum=0;
		int count=0;
		for(Iterator itr=gc.getRowKeys().iterator();itr.hasNext();){
			String rowkey = itr.next().toString();
			if(rowkey.lastIndexOf(rowSubStr)>0){
			sum += eval(exp, getParams(rowkey));
			count++;
			}
		}
		return count==0 ? 0 : sum/count;
	}
	private double computeCount(GroupCell gc) {
		return gc.getRowKeys().size();
	}
   /**
    * ���;��޸�
    * @param rowKey
    * @return
    */
	private Map getParams(Object rowKey) {
		DataTable table=this.getFoot().getReport().getDataTable();
		HashMap map=new HashMap();
		for(Iterator itr=relativeColumnKeys.entrySet().iterator();itr.hasNext();){
			Map.Entry entry=(Entry) itr.next();
			map.put(entry.getKey(),"".equals(table.getData(rowKey,entry.getValue()))?"0":table.getData(rowKey,entry.getValue()));
		}
		return map;
	}

	public Object getData(GroupCell gc) {
		String exp=expression.toUpperCase();
		
		StringBuffer buf=new StringBuffer();
		Pattern pattern=Pattern.compile("SUM\\((.+?)\\)|AVG\\((.+?)\\)|COUNT\\((\\*)\\)|SUMBYROW\\((.+?)\\)|AVGBYROW\\((.+?)\\)");
		Matcher m=pattern.matcher(exp);
		HashMap params=new HashMap();
		int paramCount=0;
		while(m.find()){
			String sumExp=m.group(1);
			String avgExp=m.group(2);
			String countExp=m.group(3);
			String sumByRowExp =m.group(4);
			String avgByRowExp = m.group(5);
			String value="0";
			if(sumExp!=null){
				value=String.valueOf(computeSum(sumExp,gc));
			}else if(avgExp!=null){
				value=String.valueOf(computeAvg(avgExp,gc));
			}else if(countExp!=null){
				value=String.valueOf(computeCount(gc));
			}else if(sumByRowExp!=null){
				value = String.valueOf(computeSumByRowKey(sumByRowExp,gc,rowKeySub));
			}else if(avgByRowExp!=null){
				value = String.valueOf(computeAvgByRowKey(avgByRowExp,gc,rowKeySub));
			}
			String name="p" + paramCount++;
			params.put(name, value);
			m.appendReplacement(buf,name);
		}	
		
		double result=eval(buf.toString(),params);
		return new Double(result);		
	}

	double eval(String exp, Map param) {
		double result=Evaluator.eval(exp,param);
		return Double.isInfinite(result) || Double.isNaN(result) ? 0 : result;
	}

	public String getRowKeySub() {
		return rowKeySub;
	}

	public void setRowKeySub(String rowKeySub) {
		this.rowKeySub = rowKeySub;
	}

	
	
}
